package com.kun.handler.tenant;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.kun.annotations.IgnoreTenantTable;
import com.kun.entity.SysUser;
import com.kun.util.LoginUserContext;
import com.kun.util.TenantContext;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;

import java.util.HashSet;
import java.util.Set;

/**
 * 默认的租户实现
 *
 * @author kun.li
 */
public class DefaultTenantLineHandler implements TenantLineHandler {

    /**
     * 忽略的表集合
     */
    private Set<String> ignoreTableSet;
    /**
     * 扫描包
     */
    private Set<String> backPackage;


    private final static String REGEX = "(?<!^)([A-Z])";


    /**
     * 租户ID的值默认为1
     *
     * @return
     */
    @Override
    public Expression getTenantId() {
        // 从网关转发过来,并且有权限的租户ID不为空,否则租户ID为空
        SysUser sysUser = LoginUserContext.getUser();
        String tenantId = sysUser.getTenantId();
        // 手动设置上下文租户ID,记得用完要关闭上下文
        if (StrUtil.isEmpty(tenantId)) {
            tenantId = TenantContext.getTenantId();
        }
        if (StrUtil.isEmpty(tenantId)) {
            tenantId = "1";
        }
        return new StringValue(tenantId);
    }

    /**
     * 忽略不进行租户的表
     *
     * @param tableName 表名
     * @return
     */
    @Override
    public boolean ignoreTable(String tableName) {
        return ignoreTableSet.stream().anyMatch(ignoreTableName -> ignoreTableName.equalsIgnoreCase(tableName));
    }


    public void setBackPackage(Set<String> backPackage) {
        this.backPackage = backPackage;
    }

    public void init() {
        this.ignoreTableSet = scanPackage(backPackage);
    }

    public static Set<String> scanPackage(Set<String> basePackages) {
        Set<String> ignoreTableSet = new HashSet<>();
        for (String basePackage : basePackages) {
            Set<Class<?>> ignoreTenantTableSet = ClassUtil.scanPackageByAnnotation(basePackage, IgnoreTenantTable.class);
            for (Class<?> ignoreTableNameClass : ignoreTenantTableSet) {
                if (ignoreTableNameClass.isAnnotationPresent(IgnoreTenantTable.class)) {
                    if (ignoreTableNameClass.isAnnotationPresent(TableName.class)) {
                        TableName annotation = ignoreTableNameClass.getAnnotation(TableName.class);
                        String value = annotation.value();
                        if (StrUtil.isEmpty(value)) {
                            String tableName = ignoreTableNameClass.getSimpleName().replaceAll(REGEX, "_$1");
                            ignoreTableSet.add(tableName.toLowerCase());
                        } else {
                            ignoreTableSet.add(value);
                        }
                    } else {
                        String tableName = ignoreTableNameClass.getSimpleName().replaceAll(REGEX, "_$1");
                        ignoreTableSet.add(tableName.toLowerCase());
                    }
                }
            }
        }
        return ignoreTableSet;
    }
}
